#light

module PubSim.Main

open System
open System.Collections.Generic
open System.Threading
open System.Configuration
open PubSim.Bartender
open PubSim.Customer
open PubSim.Assistant
open PubSim.Glasses
open PubSim.Cups
open PubSim.CappuccinoMix
open PubSim.Chocolate
open PubSim.Coffee
open PubSim.Tap

// Configuration:
let numCustomers = Convert.ToInt32(ConfigurationManager.AppSettings.Item("NumberOfCustomers"))
let numTables = Convert.ToInt32(ConfigurationManager.AppSettings.Item("MaxNumberOfTables"))
let numGlasses = Convert.ToInt32(ConfigurationManager.AppSettings.Item("NumberOfGlasses"))
let numCups = Convert.ToInt32(ConfigurationManager.AppSettings.Item("NumberOfCups"))
let waitBetweenCustomers = Convert.ToInt32(ConfigurationManager.AppSettings.Item("WaitBetweenCustomers"))

let drinkTypes = [|"coffee"; "beer"; "cappuccino"; "hot chocolate"|]

// Line to bar
let mutable customerQueue = new Queue<PubSim.Customer.Customer>()

// For logging
let mutable outputQueue = new Queue<String>()

// Create resource objects
let glasses = new PubSim.Glasses.Glasses(numGlasses)
let cups = new PubSim.Cups.Cups(numCups)
let chocolate = new PubSim.Chocolate.Chocolate(true)
let coffee = new PubSim.Coffee.Coffee(true)
let milk = new PubSim.Milk.Milk(true)
let cappuccinoMix = new PubSim.CappuccinoMix.CappuccinoMix(true)
let tap = new PubSim.Tap.Tap(true)

let tables = [| for i in 0 .. (numTables-1) -> new PubSim.Table.Table(0, 0, 0) |]

// Create people objects
let output = new PubSim.Output.Output()
let bartender1 = new PubSim.Bartender.Bartender(outputQueue, customerQueue, glasses, cups, chocolate, coffee, milk, cappuccinoMix, tap)
let bartender2 = new PubSim.Bartender.Bartender(outputQueue, customerQueue, glasses, cups, chocolate, coffee, milk, cappuccinoMix, tap)
let assistant = new PubSim.Assistant.Assistant(outputQueue, tables, glasses, cups)

// Start threads
let outputT   = new Thread(ThreadStart(fun() -> output.Start(outputQueue)))
outputT.Start()
let bartender1T = new Thread(ThreadStart(fun() -> bartender1.Start()))
bartender1T.Start()
let bartender2T = new Thread(ThreadStart(fun() -> bartender2.Start()))
bartender2T.Start()
let assistantT   = new Thread(ThreadStart(fun() -> assistant.Start()))
assistantT.Start()

// Add new customer threads
for i in 1 .. numCustomers do
  let customer = new PubSim.Customer.Customer(outputQueue, customerQueue, tables)
  let customerT   = new Thread(ThreadStart(fun() -> customer.Start()))
  customerT.Start()

  Thread.Sleep(waitBetweenCustomers)

outputQueue.Enqueue("Main: Done creating customer threads")
Console.ReadKey(true)
